package com.madhouse.config;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import static springfox.documentation.builders.PathSelectors.regex;
import static com.google.common.base.Predicates.or;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Predicate;
import com.madhouse.controller.MyController;

import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.AlternateTypeRule;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.schema.WildcardType;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableWebMvc // NOTE: Only needed in a non-springboot application
@EnableSwagger2
@ComponentScan(basePackageClasses = { MyController.class })
@Component
public class MySpringConfig {

	@Bean
	public Docket petApi() {
		return new Docket(DocumentationType.SWAGGER_2).select() // 生成Docket的选择器对API进行筛选
				.apis(RequestHandlerSelectors.any()) //针对controller进行筛选
				.paths(PathSelectors.any()) //针对路径进行筛选
				.build()
				.pathMapping("/") // API的根目录
				.directModelSubstitute(Date.class, String.class)// 输出模型的替换(把如期以字符串的形式输出)
				.genericModelSubstitutes(ResponseEntity.class) //针对泛型的处理(指定其泛型是哪种类型)
				.alternateTypeRules(new AlternateTypeRule(
						typeResolver.resolve(DeferredResult.class,
								typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
						typeResolver.resolve(WildcardType.class)))
				.useDefaultResponseMessages(false) //对于不同的http请求会产生不同的返回值
				.globalResponseMessage(RequestMethod.GET,
						newArrayList(new ResponseMessageBuilder().code(500).message("500 message")
								.responseModel(new ModelRef("Error")).build()))//定义对于错误信息的的消息和错误的模型
				.securitySchemes(newArrayList(apiKey()))//认证请求中的header
				.securityContexts(newArrayList(securityContext()))//上下文路径的认证
				.enableUrlTemplating(true);//url的模板路径
	}

	private <T> List<T> newArrayList(T t) {
		List<T> list = new ArrayList<T>();
		list.add(t);
		return list;
	}
	@Autowired
	private TypeResolver typeResolver;

	private ApiKey apiKey() {
		return new ApiKey("mykey", "api_key", "header");
	}

	private SecurityContext securityContext() {
		return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("/anyPath.*"))
				.build();
	}

	List<SecurityReference> defaultAuth() {
		AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
		AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
		authorizationScopes[0] = authorizationScope;
		return newArrayList(new SecurityReference("mykey", authorizationScopes));
	}

	@Bean
	SecurityConfiguration security() {
		return new SecurityConfiguration("test-app-client-id", "test-app-client-secret", "test-app-realm", "test-app",
				"apiKey", ApiKeyVehicle.HEADER, "api_key",
				"," /* scope separator */);
	}

//	@Bean
//	UiConfiguration uiConfig() {
//		return new UiConfiguration("validatorUrl", // url
//				"none", // docExpansion => none | list
//				"alpha", // apiSorter => alpha
//				"schema", // defaultModelRendering => schema
//				false, // enableJsonEditor => true | false
//				true); // showRequestHeaders => true | false
//	}
	
	//Here is an example where we select any api that matches one of these paths
//	  @SuppressWarnings("unchecked")
//	private Predicate<String> paths() {
//	    return or(
//	        regex("/business.*"),
//	        regex("/some.*"),
//	        regex("/contacts.*"),
//	        regex("/pet.*"),
//	        regex("/springsRestController.*"),
//	        regex("/test.*"));
//	  }
}
